package cn.newgrand.netcall.consultant.ui;

import org.jivesoftware.resource.Res;
import org.jivesoftware.spark.PluginManager;
import org.jivesoftware.spark.component.VerticalFlowLayout;
import org.jivesoftware.spark.component.panes.CollapsiblePane;
import org.jivesoftware.spark.component.renderer.JPanelRenderer;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;

import cn.newgrand.netcall.consultant.ConsultantPlugin;
import cn.newgrand.netcall.consultant.SpecialistPresenceManager;
import cn.newgrand.netcall.consultant.SpecialistQueueSizeManager;
import cn.newgrand.smackx.consultant.packet.SpecialistPresence;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;

/**
 * Container representing a RosterGroup within the Contact List.
 * Group的联系人model展示都由两块组成，一块为在线(contactItems)、一块为离线线(offlineContacts)
 * 然后对两块进行排序
 * model用户在面板中显示，包括了所有的联系人
 * 
 */
public class SpecialistGroup extends CollapsiblePane implements MouseListener {
    private List<SpecialistItem> contactItems = new ArrayList<SpecialistItem>();
    private List<SpecialistGroup> contactGroups = new ArrayList<SpecialistGroup>();
    private List<SpecialistGroupListener> listeners = new ArrayList<SpecialistGroupListener>();
    private List<SpecialistItem> offlineContacts = new ArrayList<SpecialistItem>();

    private String groupName;
    private DefaultListModel model;
    private JList contactItemList;
//    private boolean sharedGroup;
    private JPanel listPanel;
    
    // Used to display no contacts in list.
    private final SpecialistItem noContacts = new SpecialistItem(Res.getString("group.empty"), null, null);

    private final ListMotionListener motionListener = new ListMotionListener();

    private boolean canShowPopup;

    private LocalPreferences preferences;
    
    public static KeyEvent activeKeyEvent;
    
    public SpecialistGroup(){}
    
    /**
     * Create a new ContactGroup.
     *
     * @param groupName the name of the new ContactGroup.
     */
    public SpecialistGroup(String groupName) {
        // Initialize Model and UI
        model = new DefaultListModel();
        contactItemList = new JList(model);

        preferences = SettingsManager.getLocalPreferences();

        setTitle(getGroupTitle(groupName));

        // Use JPanel Renderer
        contactItemList.setCellRenderer(new JPanelRenderer());

        this.groupName = groupName;

        listPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
        listPanel.add(contactItemList, listPanel);
        this.setContentPane(listPanel);

//        if (!isOfflineGroup()) {
//            contactItemList.setDragEnabled(true);
//            contactItemList.setTransferHandler(new ContactGroupTransferHandler());
//        }

        // Allow for mouse events to take place on the title bar
//        getTitlePane().addMouseListener(new MouseAdapter() {
//            public void mousePressed(MouseEvent e) {
//                checkPopup(e);
//            }
//
//            public void mouseReleased(MouseEvent e) {
//                checkPopup(e);
//            }
//
//            public void checkPopup(MouseEvent e) {
//                if (e.isPopupTrigger()) {
//                    e.consume();
//                    fireContactGroupPopupEvent(e);
//                }
//            }
//        });

        // Items should have selection listener
        contactItemList.addMouseListener(this);

//        contactItemList.addKeyListener(new KeyListener() {
//            public void keyTyped(KeyEvent keyEvent) {
//
//            }
//
//            public void keyPressed(KeyEvent keyEvent) {
//                if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) {
//                    SpecialistItem item = (SpecialistItem)contactItemList.getSelectedValue();
//                    fireContactItemDoubleClicked(item);
//                }
//
//                SpecialistGroup.activeKeyEvent = keyEvent;
//            }
//
//            public void keyReleased(KeyEvent keyEvent) {
//            	SpecialistGroup.activeKeyEvent = null;
//            }
//        });

        noContacts.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, 12));
        noContacts.getNicknameLabel().setForeground(Color.GRAY);
        //显示该组没有联系人
//        model.addElement(noContacts);

        // Add Popup Window
        addPopupWindow();
        
       
    }

    /**
     * Adds a new offline contact.
     * 插入不在线联系人，先在在线contactItems中删除，
     * 然后再在offlineContacts中插入。
     *
     * @param alias    the alias of the offline contact.
     * @param nickname the nickname of the offline contact.
     * @param jid      the jid of the offline contact.
     * @param status   the current status of the offline contact.
     */
    public void addOfflineContactItem(String spid/*String alias*/, String nickname, String jid, String status) {
        // Build new SpecialistItem
        final SpecialistItem offlineItem = new SpecialistItem(spid, nickname, jid);
        offlineItem.setGroupName(getGroupName());

//        final Presence offlinePresence = PresenceManager.getPresence(jid);
//        offlineItem.setPresence(offlinePresence);

      final SpecialistPresence offlinePresence = SpecialistPresenceManager.getSpecialistPresence(spid);
      offlineItem.setPresence(offlinePresence);
       if(offlinePresence.isAvailable()){
    	   String queueSizeInfo = SpecialistQueueSizeManager.getInstance().getQueueSize(spid);
    	   offlineItem.setQueueSizeText(queueSizeInfo);
    	   addContactItem(offlineItem);
       }
        // set offline icon
        offlineItem.setIcon(SpecialistItem.getIconFromPresence(offlinePresence));

        // Set status if applicable.
        if (ModelUtil.hasLength(status)) {
            offlineItem.setStatusText(status);
        }

        // Add to offline contacts.
        offlineContacts.add(offlineItem);

        insertOfflineContactItem(offlineItem);
    }

    /**
     * Inserts a new offline <code>SpecialistItem</code> into the ui model.
     * 
     * 插入离线的item，加入到 offlineContacts，并改变model
     *
     * @param offlineItem the SpecialistItem to add.
     */
    public void insertOfflineContactItem(SpecialistItem offlineItem) {
        if (model.contains(offlineItem)) {
            return;
        }

        if (!preferences.isOfflineGroupVisible()) {
            Collections.sort(offlineContacts, itemComparator);
            int index = offlineContacts.indexOf(offlineItem);

            int totalListSize = contactItems.size();
            int newPos = totalListSize + index;

            if (newPos > model.size()) {
                newPos = model.size();
            }

            model.insertElementAt(offlineItem, newPos);

            if (model.contains(noContacts)) {
                model.removeElement(noContacts);
            }
        }
    }

    /**
     * Removes an offline <code>SpecialistItem</code> from the Offline contact
     * model and ui.
     *
     * @param item the offline contact item to remove.
     */
    public void removeOfflineContactItem(SpecialistItem item) {
        offlineContacts.remove(item);
        removeContactItem(item);
    }

    /**
     * Removes an offline <code>SpecialistItem</code> from the offline contact model and ui.
     *
     * @param jid the offline contact item to remove.
     */
    public void removeOfflineContactItem(String spid) {
        final List<SpecialistItem> items = new ArrayList<SpecialistItem>(offlineContacts);
        for (SpecialistItem item : items) {
            if (item.getAlias().equals(spid)) {
                removeOfflineContactItem(item);
            }
        }
    }

    /**
     * Toggles the visibility of Offline Contacts.
     * 显示离线组，并将所有离线的联系人都放到该组中
     * @param show true if offline contacts should be shown, otherwise false.
     */
    public void toggleOfflineVisibility(boolean show) {
        final List<SpecialistItem> items = new ArrayList<SpecialistItem>(offlineContacts);
        for (SpecialistItem item : items) {
            if (show) {
                insertOfflineContactItem(item);
            }
            else {
                model.removeElement(item);
            }
        }
        if (model.getSize() == 0) {
        	//显示 该组没有联系人
            //model.addElement(noContacts);
        }


    }


    /**
     * Adds a <code>SpecialistItem</code> to the ContactGroup.
     *
     * @param item the SpecialistItem.
     */
    public void addContactItem(SpecialistItem item) {
        // Remove from offline group if it exists
        removeOfflineContactItem(item.getAlias());

        if (model.contains(noContacts)) {
//            model.remove(0);
        }

        if (Res.getString("group.offline").equals(groupName)) {
            item.getNicknameLabel().setFont(new Font("Dialog", Font.PLAIN, 12));
            item.getNicknameLabel().setForeground(Color.GRAY);
        }

        item.setGroupName(getGroupName());
        contactItems.add(item);

        List<SpecialistItem> tempItems = getContactItems();


        Collections.sort(tempItems, itemComparator);


        int index = tempItems.indexOf(item);


        Object[] objs = contactItemList.getSelectedValues();

        model.insertElementAt(item, index);

        int[] intList = new int[objs.length];
        for (int i = 0; i < objs.length; i++) {
            SpecialistItem contact = (SpecialistItem)objs[i];
            intList[i] = model.indexOf(contact);
        }

        if (intList.length > 0) {
            contactItemList.setSelectedIndices(intList);
        }

//        fireContactItemAdded(item);
    }

    /**
     * Call whenever the UI needs to be updated.
     */
    public void fireContactGroupUpdated() {
        contactItemList.validate();
        contactItemList.repaint();
        updateTitle();
    }

    public void addContactGroup(SpecialistGroup contactGroup) {
        final JPanel panel = new JPanel(new GridBagLayout());
        panel.add(contactGroup, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 15, 0, 0), 0, 0));
        panel.setBackground(Color.white);
        contactGroup.setSubPane(true);

        // contactGroup.setStyle(CollapsiblePane.TREE_STYLE);
        listPanel.add(panel);
        contactGroups.add(contactGroup);
    }

	/**
	 * Removes a child ContactGroup.
	 * 
	 * @param contactGroup
	 *            the contact group to remove.
	 */
	public void removeContactGroup(SpecialistGroup contactGroup) {
		Component[] comps = listPanel.getComponents();
		try {
			for (Component comp : comps) {
				if (comp instanceof JPanel) {
					JPanel panel = (JPanel) comp;
					SpecialistGroup group = (SpecialistGroup) panel.getComponent(0);
					if (group == contactGroup) {
						listPanel.remove(panel);
						break;
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			Log.error(e.getMessage(),e);
		}

		contactGroups.remove(contactGroup);
	}

    public void setPanelBackground(Color color) {
        Component[] comps = listPanel.getComponents();
        for (Component comp : comps) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                panel.setBackground(color);
            }
        }

    }

    /**
     * Returns a ContactGroup based on it's name.
     *
     * @param groupName the name of the group.
     * @return the ContactGroup.
     */
    public SpecialistGroup getContactGroup(String groupName) {
        for (SpecialistGroup group : new ArrayList<SpecialistGroup>(contactGroups)) {
            if (group.getGroupName().equals(groupName)) {
                return group;
            }
        }

        return null;
    }

    /**
     * Removes a <code>SpecialistItem</code>.
     *
     * @param item the SpecialistItem to remove.
     */
    public void removeContactItem(SpecialistItem item) {
        contactItems.remove(item);
        if (contactItems.size() == 0) {
        	//删除子组的问题
//            removeContactGroup(this);
        }

        model.removeElement(item);
        updateTitle();

//        fireContactItemRemoved(item);
    }

    /**
     * Removes an  <code>SpecialistItem</code> from the  contact model and ui.
     *
     * @param jid the contact item to remove.
     */
    public void removeContactItem(String jid) {
        final List<SpecialistItem> items = new ArrayList<SpecialistItem>(contactItems);
        for (SpecialistItem item : items) {
            if (item.getAlias().equals(jid)) {
                removeContactItem(item);
            }
        }
    }
    
    /**
     * Returns a <code>SpecialistItem</code> by the displayed name the user has been assigned.
     *
     * @param displayName the displayed name of the user.
     * @return the SpecialistItem.
     */
    public SpecialistItem getContactItemByDisplayName(String displayName) {
        for (SpecialistItem item : new ArrayList<SpecialistItem>(contactItems)) {
            if (item.getDisplayName().equals(displayName)) {
                return item;
            }
        }
        return null;
    }

//    /**
//     * Returns a <code>SpecialistItem</code> by the users bare bareJID.
//     *
//     * @param bareJID the bareJID of the user.
//     * @return the SpecialistItem.
//     */
//    public SpecialistItem getContactItemByJID(String bareJID) {
//        for (SpecialistItem item : new ArrayList<SpecialistItem>(contactItems)) {
//            if (item.getJID().equals(bareJID)) {
//                return item;
//            }
//        }
//        return null;
//    }
    
    public SpecialistItem getContactItemBySpid(String spid) {
        for (SpecialistItem item : new ArrayList<SpecialistItem>(contactItems)) {
            if (item.getAlias().equals(spid)) {
                return item;
            }
        }
        return null;
    }
    
    public SpecialistItem getContactItemBySpid(String spid,boolean includeOffline) {
        for (SpecialistItem item : new ArrayList<SpecialistItem>(contactItems)) {
            if (item.getAlias().equals(spid)) {
                return item;
            }
        }
        if(includeOffline){
	        for (SpecialistItem item : new ArrayList<SpecialistItem>(offlineContacts)) {
	            if (item.getAlias().equals(spid)) {
	                return item;
	            }
	        }
        }
        return null;
    }
    /**
     * Returns all <code>SpecialistItem</cod>s in the ContactGroup.
     *
     * @return all ContactItems.
     */
    public List<SpecialistItem> getContactItems() {
        final List<SpecialistItem> list = new ArrayList<SpecialistItem>(contactItems);
        Collections.sort(list, itemComparator);
        return list;
    }
    
    public List<SpecialistItem> getContactItems(boolean includeOffline) {
        final List<SpecialistItem> list = new ArrayList<SpecialistItem>(contactItems);
        if(includeOffline){
        	final List<SpecialistItem> list2 = new ArrayList<SpecialistItem>(offlineContacts);
        	list.addAll(list2);
        }
        Collections.sort(list, itemComparator);
        return list;
    }
    /**
     * Returns the name of the ContactGroup.
     *
     * @return the name of the ContactGroup.
     */
    public String getGroupName() {
        return groupName;
    }


    public void mouseClicked(MouseEvent e) {

        Object o = contactItemList.getSelectedValue();
        if (!(o instanceof SpecialistItem)) {
            return;
        }

        // Iterator through rest
        SpecialistItem item = (SpecialistItem)o;

        if (e.getClickCount() == 2) {
            fireContactItemDoubleClicked(item);
        }
        else if (e.getClickCount() == 1) {
            fireContactItemClicked(item);
        }
    }

    public void mouseEntered(MouseEvent e) {
        int loc = contactItemList.locationToIndex(e.getPoint());

        Object o = model.getElementAt(loc);
        if (!(o instanceof SpecialistItem)) {
            return;
        }

        contactItemList.setCursor(GraphicUtils.HAND_CURSOR);
    }

    public void mouseExited(MouseEvent e) {
//        Object o;
//        try {
//            int loc = contactItemList.locationToIndex(e.getPoint());
//            if (loc == -1) {
//                return;
//            }
//
//            o = model.getElementAt(loc);
//            if (!(o instanceof SpecialistItem)) {
//                ContactInfoWindow.getInstance().dispose();
//                return;
//            }
//        }
//        catch (Exception e1) {
//            Log.error(e1);
//            return;
//        }
//
//        contactItemList.setCursor(GraphicUtils.DEFAULT_CURSOR);

    }

    public void mousePressed(MouseEvent e) {
        checkPopup(e);
    }

    public void mouseReleased(MouseEvent e) {
        checkPopup(e);
    }

    private void checkPopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            // Otherwise, handle single selection
            int index = contactItemList.locationToIndex(e.getPoint());
            if (index != -1) {
                int[] indexes = contactItemList.getSelectedIndices();
                boolean selected = false;
                for (int o : indexes) {
                    if (index == o) {
                        selected = true;
                    }
                }

                if (!selected) {
                    contactItemList.setSelectedIndex(index);
                    fireContactItemClicked((SpecialistItem)contactItemList.getSelectedValue());
                }
            }


            //final Collection selectedItems = SparkManager.getChatManager().getSelectedContactItems();
            final Collection selectedItems = ((ConsultantPlugin)PluginManager.getInstance().getPlugin(ConsultantPlugin.class)).getSpecialistList().getSelectedUsers();
            if (selectedItems.size() > 1) {
                firePopupEvent(e, selectedItems);
            }
            else if (selectedItems.size() == 1) {
                final SpecialistItem contactItem = (SpecialistItem)selectedItems.iterator().next();
                firePopupEvent(e, contactItem);
            }
        }
    }

    /**
     * Add a <code>ContactGroupListener</code>.
     *
     * @param listener the ContactGroupListener.
     */
    public void addContactGroupListener(SpecialistGroupListener listener) {
        listeners.add(listener);
    }

    /**
     * Removes a <code>ContactGroupListener</code>.
     *
     * @param listener the ContactGroupListener.
     */
    public void removeContactGroupListener(SpecialistGroupListener listener) {
        listeners.remove(listener);
    }

    private void fireContactItemClicked(SpecialistItem item) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.contactItemClicked(item);
        }
    }

    private void fireContactItemDoubleClicked(SpecialistItem item) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.contactItemDoubleClicked(item);
        }
    }


    private void firePopupEvent(MouseEvent e, SpecialistItem item) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.showPopup(e, item);
        }
    }

    private void firePopupEvent(MouseEvent e, Collection items) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.showPopup(e, items);
        }
    }

    private void fireContactGroupPopupEvent(MouseEvent e) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.contactGroupPopup(e, this);
        }
    }

    private void fireContactItemAdded(SpecialistItem item) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.contactItemAdded(item);
        }
    }

    private void fireContactItemRemoved(SpecialistItem item) {
        for (SpecialistGroupListener contactGroupListener : new ArrayList<SpecialistGroupListener>(listeners)) {
            contactGroupListener.contactItemRemoved(item);
        }
    }

    private void updateTitle() {
        if (Res.getString("group.offline").equals(groupName)) {
            setTitle(Res.getString("group.offline"));
            return;
        }

        int count = 0;
        List<SpecialistItem> list = new ArrayList<SpecialistItem>(getContactItems());
        int size = list.size();
        for (int i = 0; i < size; i++) {
            SpecialistItem it = list.get(i);
            if (it.isAvailable()) {
                count++;
            }
        }

//        setTitle(getGroupTitle(groupName) + " [" + count + "/" +model.getSize()+ "]");
//        setTitle(getGroupTitle(groupName) + " (" + size + "/" +model.getSize() + Res.getString("online") + ")");
        setTitle(getGroupTitle(groupName) + " ("+ count + Res.getString("online") + ")");


        if (model.getSize() == 0) {
        	//显示该组没有联系人
          // model.addElement(noContacts);
        }
    }

    /**
     * Returns the containing <code>JList</code> of the ContactGroup.
     *
     * @return the JList.
     */
    public JList getList() {
        return contactItemList;
    }

    /**
     * Clears all selections within this group.
     */
    public void clearSelection() {
        contactItemList.clearSelection();
    }

    public void removeAllContacts() {
        // Remove all users from online group.
        for (SpecialistItem item : new ArrayList<SpecialistItem>(getContactItems())) {
            removeContactItem(item);
        }

        // Remove all users from offline group.
        for (SpecialistItem item : getOfflineContacts()) {
            removeOfflineContactItem(item);
        }
    }

    /**
     * Returns true if the ContactGroup contains available users.
     *
     * @return true if the ContactGroup contains available users.
     */
    public boolean hasAvailableContacts() {
        for (SpecialistGroup group : contactGroups) {
            if (group.hasAvailableContacts()) {
                return true;
            }
        }

        for (SpecialistItem item : getContactItems()) {
            if (item.getPresence() != null) {
                return true;
            }
        }
        return false;
    }

    public Collection<SpecialistItem> getOfflineContacts() {
        return new ArrayList<SpecialistItem>(offlineContacts);
    }

    /**
     * Sorts ContactItems.
     */
    final Comparator<SpecialistItem> itemComparator = new Comparator<SpecialistItem>() {
        public int compare(SpecialistItem item1, SpecialistItem item2) {
            return item1.getDisplayName().toLowerCase().compareTo(item2.getDisplayName().toLowerCase());
        }
    };

    /**
     * Returns true if this ContactGroup is the Offline Group.
     *
     * @return true if OfflineGroup.
     */
    public boolean isOfflineGroup() {
        return Res.getString("group.offline").equals(getGroupName());
    }

    /**
     * Returns true if this ContactGroup is the Unfiled Group.
     *
     * @return true if UnfiledGroup.
     */
    public boolean isUnfiledGroup() {
        //TODO: Don't identify the unfiled group by name, because the user
        //could have a custom group of that name.

        return Res.getString("unfiled").equals(getGroupName());
    }

    public String toString() {
        return getGroupName();
    }

//    /**
//     * Returns true if ContactGroup is a Shared Group.
//     *
//     * @return true if Shared Group.
//     */
//    public boolean isSharedGroup() {
//        return sharedGroup;
//    }

//    /**
//     * Set to true if this ContactGroup is a shared Group.
//     *
//     * @param sharedGroup true if shared group.
//     */
//    protected void setSharedGroup(boolean sharedGroup) {
//        this.sharedGroup = sharedGroup;
//        if (sharedGroup) {
//            setToolTipText(Res.getString("message.is.shared.group", getGroupName()));
//        }
//    }

    /**
     * Returns all Selected Contacts within the ContactGroup.
     *
     * @return all selected ContactItems.
     */
    public List<SpecialistItem> getSelectedContacts() {
        final List<SpecialistItem> items = new ArrayList<SpecialistItem>();
        Object[] selections = contactItemList.getSelectedValues();
        final int no = selections != null ? selections.length : 0;
        for (int i = 0; i < no; i++) {
            try {
                SpecialistItem item = (SpecialistItem)selections[i];
                items.add(item);
            }
            catch (NullPointerException e) {
                // TODO: Evaluate if we should do something here.
            }
        }
        return items;
    }

    public JPanel getContainerPanel() {
        return listPanel;
    }

    public Collection<SpecialistGroup> getContactGroups() {
        return contactGroups;
    }

    /**
     * Lets make sure that the panel doesn't stretch past the
     * scrollpane view pane.
     *
     * @return the preferred dimension
     */
    public Dimension getPreferredSize() {
        final Dimension size = super.getPreferredSize();
        size.width = 0;
        return size;
    }

    /**
     * Sets the name of group.
     *
     * @param groupName the contact group name.
     */
    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    /**
     * Returns the "pretty" title of the ContactGroup.
     *
     * @param title the title.
     * @return the new title.
     */
    public String getGroupTitle(String title) {
        int lastIndex = title.lastIndexOf("::");
        if (lastIndex != -1) {
            title = title.substring(lastIndex + 2);
        }

        return title;
    }

    /**
     * Returns true if the group is nested.
     *
     * @param groupName the name of the group.
     * @return true if the group is nested.
     */
    public boolean isSubGroup(String groupName) {
        return groupName.indexOf("::") != -1;
    }

    /**
     * Returns true if this group is nested.
     *
     * @return true if nested.
     */
    public boolean isSubGroup() {
        return isSubGroup(getGroupName());
    }

    /**
     * Returns the underlying container for the JList.
     *
     * @return the underlying container of the JList.
     */
    public JPanel getListPanel() {
        return listPanel;
    }

    /**
     * Adds an internal popup listesner.
     */
    private void addPopupWindow() {
        final Timer timer = new Timer(500, new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                canShowPopup = true;
            }
        });

        contactItemList.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent mouseEvent) {
                timer.start();
            }

            public void mouseExited(MouseEvent mouseEvent) {
                timer.stop();
                canShowPopup = false;
                SpecialistInfoWindow.getInstance().dispose();
            }
        });


        contactItemList.addMouseMotionListener(motionListener);
    }


    private class ListMotionListener extends MouseMotionAdapter {

        public void mouseMoved(MouseEvent e) {
            if (!canShowPopup) {
                return;
            }

            if (e == null) {
                return;
            }
            displayWindow(e);
        }
    }
    
    /**
     * 鼠标移动到联系人上面时更改背景色
     *
     * @param e the mouseEvent that triggered this event.
     */
    private void changeBackGround(MouseEvent e) {
    	int loc = this.getList().locationToIndex(e.getPoint());
    	SpecialistItem item = (SpecialistItem)this.getList().getModel().getElementAt(loc);
    	item.setOpaque(true);
    	item.setBackground((Color)UIManager.get("List.focusBackground"));
    }
    /**
     * Displays the <code>ContactInfoWindow</code>.
     *
     * @param e the mouseEvent that triggered this event.
     */
    private void displayWindow(MouseEvent e) {
   	 if(preferences.areVCardsVisible())
   		 SpecialistInfoWindow.getInstance().display(this, e);
    }
    /**
     * get offline contactItem in the group
     * 
     * @param JID
     * @return
     */
//    public SpecialistItem getOfflineContactItemByJID(String JID){
//    	for (SpecialistItem item : new ArrayList<SpecialistItem>(getOfflineContacts())) {
//            if (item.getJID().equals(JID)) {
//                return item;
//            }
//        }
//        return null;
//    }
    
	  public SpecialistItem getOfflineContactItemBySpid(String spid){
		for (SpecialistItem item : new ArrayList<SpecialistItem>(getOfflineContacts())) {
	        if (item.getAlias().equals(spid)) {
	            return item;
	        }
	    }
	    return null;
	}
}






